home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/perl
- #
- # Copyright (C)2004 Giuseppe Giunto
- # Reads data from iPodDB
- # URL: http://www.hyperbolicsoftware.com/
- #
- # Uses code from tunes2html.pl
- # Copyright (C) 2003-2004 Joe Mallon <jmmallon at joescafe dot com>
- # URL: http://www.joescafe.com/tunes2html
- #
- # iTunes, and iPod are registered trademarks of Apple Computer, Inc.
- #
- # This product is not supported/written/published by Apple!
- #
-
- sub get_nod_a($);
-
- $itdbPath = @ARGV[0];
- $iTunesVers = @ARGV[1];
-
- $ipodmagic = "6d 68 62 64 68 00 00 00";
-
- open(FILE, $itdbPath) or die "Can't open input file: $!\n";
-
- #check the header
- if(getfoo(0, (length($ipodmagic)+2)/3) ne $ipodmagic) {
- die "err: could open $file, but:\nI don't think, thats an ipod - tunes db!\n";
- }
-
- $qq = 292; #the magic number!! (the HARDCODED start of the first mhit)
-
- # gnutunes header
- while($qq != -1) {
- %info = ();
- ($qq,$stuffptr) = get_nod_a($qq); #get_nod_a returns wher it's guessing the next MHIT, if it fails, it returns '-1'
-
- if (defined(%$stuffptr)) {
- %info = %$stuffptr;
-
- $artist = $info{'artist'};
- $path = $info{'path'};
- $year = (defined($info{'year'})) ? $info{'year'} : "";
- $song = $info{'song'};
- $album = ($info{'album'}) ? $info{'album'} : "";
- $track = (defined($info{'track'})) ? $info{'track'} : 0;
- $size = $info{'size'};
- $id = $info{'id'};
-
- print $song."*_*".$artist."*_*".$album."*_*".$year."*_*".$track."*_*".$size."*_*".$path."*_*".$id."#_#";
- }
- }
-
- close(FILE);
-
- sub get_nod_a($)
- {
- my(@jerk, $sum, $zip, $otxt, $oid);
- my %stuff = ();
- ($sum) = @_;
- if(getfoo($sum, 4) eq "6d 68 69 74") { #aren't we lost?
-
- $stuff{'id'} = getshoe($sum+16 , 4);
- $stuff{'size'} = getshoe($sum+36 , 4);
- $stuff{'length'} = int(getshoe($sum+40,4)/1000);
- $stuff{'track'} = getshoe($sum+44,4); #song number
- $stuff{'year'} = getshoe($sum+52,4); #year
-
- $sum += ($iTunesVers > 46) ? 244 : 156; #1st mhod starts here!
- while($zip != -1) {
- $sum = $zip+$sum;
- ($zip, $oid, $otxt) = get_mhod($sum); #returns the number where its guessing the next mhod, -1 if it's failed
- $jerk[$oid] = xmlstring($otxt);
- }
-
- $stuff{'song'} = $jerk[1];
- $stuff{'path'} = $jerk[2];
- $stuff{'album'} = $jerk[3];
- $stuff{'artist'} = $jerk[4];
- # $stuff{'sortart'} = $jerk[12];
-
- return ($sum-$zip-1,\%stuff); #black magic
- } else {
- return "-1";
- }
- }
-
- #get a SINGLE mhod entry:
- #
- # get_mhod(START_OF_MHOD);
- #
- # return+seek = new_mhod should be there
- sub get_mhod()
- {
- my($seek, $xl, $ml, $mty, $foo, $id);
- ($seek) = @_;
-
- $id = getfoo($seek, 4); #are we lost?
-
- $ml = getshoe($seek+8, 4);
- $mty = getshoe($seek+12, 4); #genre number
- $xl = getshoe($seek+28,4); #Entrylength
-
- if($id ne "6d 68 6f 64") { #is the id INcorrect??
- $ml = -1;
- } else {
- #get the TYPE of the DB-Entry
- $foo = getstr($seek+40, $xl); #string of the entry
- $foo =~ tr/\0//d; #we have many \0.. killem!
-
- return ($ml, $mty, $foo);
- }
- }
-
- sub getfoo {
- #reads $anz chars from FILE and returns HEX values!
- my($anz, $buffer, $xx, $xr, $start, $noseek);
- ($start, $anz, $noseek) = @_;
- # paranoia checks
- if(!$start) { $start = 0; }
- if(!$anz) { $anz = "1"; }
-
- #seek to the given position
-
- seek(FILE, $start, 0);
- #start reading
- read(FILE, $buffer, $anz);
- foreach(split(//, $buffer)) {
- $xx = sprintf("%02x ", ord($_));
- $xr = "$xr$xx";
- }
- chop($xr);# no whitespace at end
-
- return $xr;
- }
-
- sub getshoe
- {
- #reads $anz chars from FILE and returns int
- my($anz, $buffer, $xx, $xr, $start, $noseek, $xxt);
- ($start, $anz, $noseek) = @_;
-
- # paranoia checks
- if(!$start) { $start = 0; }
- if(!$anz) { $anz = "1"; }
-
- #seek to the given position
- seek(FILE, $start, 0);
-
- #start reading
- read(FILE, $buffer, $anz);
- foreach(split(//, $buffer)) {
- $xx = sprintf("%02X", ord($_));
- $xr = "$xx$xr";
- }
- $xr = oct("0x".$xr);
- return $xr;
- }
-
- sub getstr
- {
- #reads $anz chars from FILE and returns a string!
- my($anz, $buffer, $xx, $xr, $start, $noseek);
- ($start, $anz, $noseek) = @_;
- # paranoia checks
- if(!$start) { $start = 0; }
- if(!$anz) { $anz = "1"; }
-
- #seek to the given position
- #if 3th ARG isn't defined
-
- seek(FILE, $start, 0);
- #start reading
- read(FILE, $buffer, $anz);
-
- return $buffer;
- }
-
- sub xmlstring
- {
- my($ret) = @_;
- $ret =~ s/&/&/g;
- $ret =~ s/"/"/g;
- $ret =~ s/</</g;
- $ret =~ s/>/>/g;
- $ret =~ s/'/'/g;
- return $ret;
- }
-
-